Skip to content

feat(dialtone-cli,dialtone-query-core): DLT-3163 extract query core and add CLI#1142

Merged
Brad Paugh (braddialpad) merged 6 commits intostagingfrom
feat/DLT-3163-dialtone-cli
Mar 24, 2026
Merged

feat(dialtone-cli,dialtone-query-core): DLT-3163 extract query core and add CLI#1142
Brad Paugh (braddialpad) merged 6 commits intostagingfrom
feat/DLT-3163-dialtone-cli

Conversation

@hynes-dialpad
Copy link
Copy Markdown
Member

@hynes-dialpad Joshua Hynes (hynes-dialpad) commented Mar 19, 2026

Obligatory GIF (super important!)

Obligatory GIF

🛠️ Type Of Change

  • Feature

📖 Jira Ticket

DLT-3163

📖 Description

Extracts the search engine from dialtone-mcp-server into a shared dialtone-query-core package, then builds a new dialtone-cli on top of it.

New packages:

  • @dialpad/dialtone-query-core — shared search engine (types, search functions, filters, data loading). Built with tsc, consumed by both MCP server and CLI.
  • @dialpad/dialtone-cli — terminal interface for searching components, tokens, utility classes, and icons. Built with rollup + citty.

Refactored:

  • @dialpad/dialtone-mcp-server — now imports from dialtone-query-core instead of owning the search logic. All existing behavior preserved (99% test pass rate unchanged).

CLI commands:

Command Purpose
dialtone search <query> Cross-domain search, supports | for OR
dialtone component <name> Component docs with --props, --prop <name>, --events, --slots, --describe
dialtone token <query> Token lookup with --values, --all for HSL
dialtone utility <query> CSS utility class lookup
dialtone prompt <name> LLM-optimized compact context block

All commands support --format minimal (default), --format markdown, --format json, and --limit.

💡 Context

The CLI exists as a token-efficient complement to the MCP server for AI agent workflows. MCP returns JSON over a protocol layer that costs context window tokens. The CLI returns plain text — same data, fewer tokens. Install both: CLI for fast lookups, MCP for deep exploration via resources.

Search improvements (in core, affects both CLI and MCP):

  • HSL decomposition tokens filtered by default (559 → 91 results for "foreground color"). Pass --all / { includeHsl: true } to include them.
  • Component search now handles camelCase queries (DtButton resolves correctly).
  • OR search via pipe separator (input|select|menu).

📦 Cross-Package Impact

Package Changes Downstream Impact
dialtone-query-core New — extracted search engine Foundation for MCP server and CLI
dialtone-mcp-server Refactored to import from core No public API changes, identical behavior
dialtone-cli New — terminal interface Available via pnpm dialtone or global install
Root package.json Added @dialpad/dialtone-cli dependency dialtone bin available in monorepo

Dependency flow: tokens → CSS → Vue → query-core → MCP server / CLI

📝 Checklist

For all PRs:

  • I have ensured no private Dialpad links or info are in the code or pull request description (Dialtone is a public repo!).
  • I have reviewed my changes.
  • I have added all relevant documentation.
  • I have considered the performance impact of my change.

🔮 Next Steps

  • Publish @dialpad/dialtone-query-core and @dialpad/dialtone-cli to npm
  • Add Vitest test suite for dialtone-query-core
  • Consider adding dialtone and dialtone-mcp-server bins to root @dialpad/dialtone package
  • Document recommended Claude Code setup in other Dialpad repos (firespotter, web-clients)

…nd add CLI

Extract search logic from dialtone-mcp-server into a shared
dialtone-query-core package. Create dialtone-cli as a token-efficient
terminal interface to the same search engine.

- dialtone-query-core: types, search functions, filters, data loading
- dialtone-cli: search, component, token, utility, prompt commands
- dialtone-mcp-server: refactored to import from query-core
- HSL decomposition tokens filtered from search results by default
- Component search now handles camelCase queries (DtButton works)
- OR search support via pipe separator (input|select|menu)
@wiz-inc-55b470eb7e
Copy link
Copy Markdown

wiz-inc-55b470eb7e Bot commented Mar 19, 2026

Wiz Scan Summary

Scanner Findings
Vulnerability Finding Vulnerabilities -
Data Finding Sensitive Data -
Secret Finding Secrets -
IaC Misconfiguration IaC Misconfigurations -
SAST Finding SAST Findings -
Software Management Finding Software Management Findings -
Total -

View scan details in Wiz

To detect these findings earlier in the dev lifecycle, try using Wiz Code VS Code Extension.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5bcb9b6c5a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "Codex (@codex) review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "Codex (@codex) address that feedback".

Comment thread packages/dialtone-query-core/package.json
CLI now resolves data from the project's installed Dialtone packages
(via Node module resolution) before falling back to bundled data.
This ensures search results match the project's pinned version.

- Uses createRequire rooted at cwd for pnpm/npm/workspace compat
- Shows "Using local Dialtone data (vX.Y.Z)" on stderr when detected
- --bundled flag forces use of CLI's built-in data
Fix data resolver to use the correct export-mapped specifiers for
the @dialpad/dialtone umbrella package (css/* not dist/css/*).
Tested against beacon-app (next) and firespotter (stable).
* "DtButton" → ["Dt", "Button"]
*/
function splitCamelCase(name: string): string[] {
return name.replace(/([A-Z])/g, ' $1').trim().split(' ').map(w => w.toLowerCase());
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This gives 'D t B utton'. So a name-bucket search for "button" against DtButton won't match.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified — splitCamelCase("DtButton") actually returns ["dt", "button"], not ["d", "t", "b", "utton"]. The regex ([A-Z]) inserts a space before each uppercase letter, but consecutive lowercase letters stay grouped: " Dt Button" → trim → split → ["Dt", "Button"].

It would break on consecutive uppercase like DtRTE["dt", "r", "t", "e"], but we don't have component names like that in the library.

Comment thread packages/dialtone-cli/src/silence-debug.ts Outdated
Comment thread packages/dialtone-query-core/src/tools/tokens.ts Outdated
Comment thread packages/dialtone-cli/src/formatters.ts Outdated
- silence-debug: use explicit core debug prefix allowlist instead of
  blanket [* match that swallowed Node warnings
- HSL filter: scope regex to color tokens only (--dt-*color*-h/s/l/a)
- prompt formatter: split on sentence boundaries (period + uppercase)
  instead of any period + space, avoiding e.g./i.e. false splits
Comment thread packages/dialtone-cli/src/formatters.ts Outdated
Comment thread packages/dialtone-cli/src/formatters.ts Outdated
Comment thread packages/dialtone-cli/src/formatters.ts Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the main question I have here, is does dialtone-query-core need to be a "package"? I think it would depend on what we are planning on doing with it in the future, but right now it's basically just a library of functions that are not intended for external use and are only used internally. It has it's own package.json / project.json / ci config etc which are all really only necessary for externally consumed packages. The way it is being used now, we could just as easily add a new directory called dialtone_query_core in dialtone/common and it would be a whole lot simpler to just import from that folder in both projects. Wouldn't have to worry about package dependencies or the release pipeline or anything.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point. The core is internal-only right now and a common/ folder would eliminate the package.json, project.json, release config, and the workspace dependency ceremony.

The trade-off is build orchestration. As a package, NX handles the build ordering automatically (dependsOn: ["dialtone-query-core:build"]), and both consumers resolve it cleanly via workspace:*. Moving to common/ means:

  • Each consumer's tsconfig needs to include common/ in its compilation scope
  • Rollup configs need relative path aliases instead of package resolution
  • NX build ordering becomes implicit (no dependsOn, just hope the files are there)

None of that is hard, but it's swapping one kind of config for another. If the team prefers common/, happy to move it — it's a straightforward refactor. The search logic and API surface don't change either way.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it's a good point about the nx build ordering. I think we should keep it the way it is, maybe we can remove the release-ci.config.cjs and the publish and release targets from project.json so it's clear it's not releaseable.

Comment thread packages/dialtone-cli/src/formatters.ts
…table3

Addresses review feedback: duplicate code, identical variables, and
iteration order concerns all resolved by replacing the custom
borderedTable function with cli-table3. Also adds word-wrap for long
descriptions and values.
Copy link
Copy Markdown
Contributor

@braddialpad Brad Paugh (braddialpad) left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, let's potentially remove the "release" config from dialtone-query-core before merging

dialtone-query-core is internal-only — it's bundled into dialtone-mcp-server
and dialtone-cli at build time, never published independently. Remove the
release pipeline and publish targets per review feedback.
@braddialpad Brad Paugh (braddialpad) merged commit 65090e6 into staging Mar 24, 2026
9 checks passed
@braddialpad Brad Paugh (braddialpad) deleted the feat/DLT-3163-dialtone-cli branch March 24, 2026 20:17
Brad Paugh (braddialpad) pushed a commit that referenced this pull request Mar 25, 2026
# [1.3.0-next.2](dialtone-mcp-server/v1.3.0-next.1...dialtone-mcp-server/v1.3.0-next.2) (2026-03-25)

### Features

* **Dialtone Cli,dialtone Query Core:** DLT-3163 extract query core and add CLI ([#1142](#1142)) ([65090e6](65090e6))
Brad Paugh (braddialpad) pushed a commit that referenced this pull request Mar 25, 2026
# [9.176.0-next.1](dialtone/v9.175.2...dialtone/v9.176.0-next.1) (2026-03-25)

### Bug Fixes

* **Doc:** NO-JIRA correct font size utility json ([#1015](#1015)) ([76cf0fa](76cf0fa))
* **Editor:** NO-JIRA remove extra blank line in editor.mdx ([18c47ef](18c47ef))
* possible merge issue in sidebarItem.vue ([5e2e91b](5e2e91b))
* **Rich Text Editor:** DLT-3190 replace custom JSON-to-markdown converter with @tiptap/static-renderer ([#1148](#1148)) ([9629c70](9629c70))
* **Stylelint:** disable hue-degree-notation rule and update OKLCH color syntax ([81f886e](81f886e))
* **Stylelint:** disable hue-degree-notation rule and update OKLCH color syntax ([8721f43](8721f43))
* **Tokens:** DLT-3053 preserve root font size variable as reference ([#1093](#1093)) ([112ab4b](112ab4b))
* **Tokens:** handle multi-layer box shadows correctly in postcss plugin ([feea7f1](feea7f1))
* **Tokens:** NO-JIRA output line-height as unitless instead of percentages ([#1040](#1040)) ([33d8505](33d8505))
* **Tokens:** wrap css math expressions with calc() in layered build ([#966](#966)) ([1635f61](1635f61))
* update @dialpad/i18n dependencies to latest versions ([7a4b777](7a4b777))

### Code Refactoring

* **Combobox Multi Select:** NO-JIRA use logical css properties ([#1104](#1104)) ([a675daf](a675daf))
* **Components,recipes:** DLT-3043 DLT-3046 logical start/end naming with deprecated backward-compatible fallbacks ([#1079](#1079)) ([1d26a4e](1d26a4e))
* **Css:** DLT-1876 css logical properties ([#872](#872)) ([1acd6c9](1acd6c9))
* **Style:** DLT-3014 wrap all styles in css cascade layers ([#1061](#1061)) ([f8b3fed](f8b3fed))
* **Text:** DLT-2883 rename headline sizes from xxl => 2xl, etc ([#1029](#1029)) ([0ac86f3](0ac86f3))
* **Tokens,css,link,text,breadcrumbs,input Group,split Button:** tokens, CSS foundation, deprecations, tooling DLT-3011 DLT-2961 DLT-3068 DLT-3069 DLT-3070 DLT-3071 DLT-3072 ([#1092](#1092)) ([7783090](7783090))
* **Tokens:** DLT-2884 deprecate space tokens in favor of size tokens ([#1013](#1013)) ([63f6d2f](63f6d2f))
* **Tokens:** DLT-3013 convert color system from HSL to OKLCH ([#1060](#1060)) ([42dc418](42dc418))

### Documentation

* **Components:** DLT-3178 DLT-3182 unify code examples into single code-example component ([#1147](#1147)) ([d0b6e14](d0b6e14))
* DLT-1510 DLT-1511 DLT-1512 site redesign and ia ([#968](#968)) ([6ea7eb9](6ea7eb9))
* DLT-2908 ui kits landing page ([#1049](#1049)) ([d805b9d](d805b9d))
* **Editor:** DLT-3050 updated editor docs with recent changes ([#1139](#1139)) ([04bfabb](04bfabb))
* **Icons:** DLT-3220 update contributing and add claude rules and skill ([#1151](#1151)) ([296a83d](296a83d))
* NO-JIRA fix focus left-nav items on keypress down up ([#1106](#1106)) ([882c9b9](882c9b9))
* **Playground:** DLT-3119 refine playground UI and integrate across doc site ([#1127](#1127)) ([ba6b599](ba6b599))

### Features

* **Avatar:** DLT-2942 updated avatar component ([#1047](#1047)) ([e50563d](e50563d))
* **Banner, Notice, Toast, Breadcrumbs, Checkbox, Radio, Input, Select Menu, Empty State:** visual refresh, dt-text integration, form api parity DLT-2944 DLT-2945 DLT-2949 DLT-2959 DLT-2960 DLT-2957 ([#1091](#1091)) ([16e908a](16e908a))
* **Button,tabs,split Button:** visual refresh and slot updates DLT-2946 DLT-2947 DLT-2965 ([#1090](#1090)) ([ffdd56f](ffdd56f))
* **Css Utility:** DLT-2715 add default color for border css utilities ([#874](#874)) ([71310ab](71310ab))
* **Dialtone Cli,dialtone Query Core:** DLT-3163 extract query core and add CLI ([#1142](#1142)) ([65090e6](65090e6))
* **Filter Pill:** DLT-2704 create component ([#473](#473)) ([6267445](6267445))
* **Filter Pill:** DLT-2941 DtFilterPill improvements ([#1110](#1110)) ([23c5689](23c5689))
* **Icons:** DLT-3219 align star/sparkle icons with dp brand star ([#1152](#1152)) ([ef39afc](ef39afc))
* **Link,button:** DLT-3012 add underline prop ([#1059](#1059)) ([1cb91ea](1cb91ea))
* **Mode Directive, Mode Island:** DLT-3067 DLT-3078 DLT-3077 add `v-dt-mode` directive ([#1109](#1109)) ([f97efca](f97efca))
* **Segmented Control:** DLT-413 new component ([#1144](#1144)) ([ad4c6c3](ad4c6c3))
* **Style:** DLT-2976 update underline thickness and offset ([#1058](#1058)) ([1e56947](1e56947))
* **Tabs:** DLT-3114 add vertical orientation variant ([#1120](#1120)) ([3290a23](3290a23))
* **Tabs:** DLT-3162 add spread prop for horizontal distribution ([#1135](#1135)) ([6e7cd04](6e7cd04))
* **Text:** export text component from dialtone-vue ([757fdb7](757fdb7))
* **Text:** new vue component DLT-2864 DLT-2863 DLT-2862 ([#995](#995)) ([196ef8a](196ef8a))
* **Tokens:** DLT-1977 add high contrast design tokens and theme ([#938](#938)) ([a1c0457](a1c0457))
* **Tokens:** DLT-2767 exploratory shell themes ([#909](#909)) ([3afcf63](3afcf63))
* **Tokens:** DLT-2781 create color-assistive themes ([#921](#921)) ([a6cc397](a6cc397))
* **Tokens:** DLT-2802 DLT-2563 layered theming system and mode island component ([#945](#945)) ([5c72c6c](5c72c6c))
* **Tokens:** DLT-2937 introduce spacing and layout token systems ([#1045](#1045)) ([de23e12](de23e12))
* **Tokens:** update color ramps and consumer color migration tools DLT-3004 DLT-3005 DLT-3006 DLT-3007 DLT-3008 ([#1054](#1054)) ([28cb1de](28cb1de))
* **Typography, Tokens:** DLT-2856 DLT-2857 next typography system ([#994](#994)) ([d744e97](d744e97))
Brad Paugh (braddialpad) pushed a commit that referenced this pull request Mar 31, 2026
# [1.3.0](dialtone-mcp-server/v1.2.1...dialtone-mcp-server/v1.3.0) (2026-03-31)

### Features

* **Dialtone Cli,dialtone Query Core:** DLT-3163 extract query core and add CLI ([#1142](#1142)) ([65090e6](65090e6))
Brad Paugh (braddialpad) pushed a commit that referenced this pull request Mar 31, 2026
# [9.176.0](dialtone/v9.175.2...dialtone/v9.176.0) (2026-03-31)

### Bug Fixes

* **Rich Text Editor:** DLT-3190 replace custom JSON-to-markdown converter with @tiptap/static-renderer ([#1148](#1148)) ([9629c70](9629c70))

### Documentation

* DLT-3151 blog post for ui-kits migration and script ([#1156](#1156)) ([069ad3c](069ad3c))
* **Editor:** DLT-3050 updated editor docs with recent changes ([#1139](#1139)) ([04bfabb](04bfabb))
* **Icons:** DLT-3220 update contributing and add claude rules and skill ([#1151](#1151)) ([296a83d](296a83d))

### Features

* **Dialtone Cli,dialtone Query Core:** DLT-3163 extract query core and add CLI ([#1142](#1142)) ([65090e6](65090e6))
* DLT-3049 add code review rules, skill, agent, and command ([#1154](#1154)) ([6bdef46](6bdef46))
* **Icons:** DLT-3219 align star/sparkle icons with dp brand star ([#1152](#1152)) ([ef39afc](ef39afc))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants